package de.devisnik.eidle.app;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
import org.eclipse.ui.progress.UIJob;

import de.devisnik.eidle.EidlePreferences;
import de.devisnik.eidle.util.Parameters;
import de.devisnik.eidle.util.ScreenUtils;

public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor {

	private final Parameters parameters;

	public ApplicationWorkbenchWindowAdvisor(
			final IWorkbenchWindowConfigurer configurer,
			final Parameters parameters) {
		super(configurer);
		this.parameters = parameters;
	}

	public ActionBarAdvisor createActionBarAdvisor(
			final IActionBarConfigurer configurer) {
		return new ApplicationActionBarAdvisor(configurer);
	}

	public void preWindowOpen() {
		if (parameters.isSaverMode()) {
			setFullScreenMode();
		} else {
			setWindowMode();
		}
	}

	private void setWindowMode() {
		final IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
		configurer.setInitialSize(new Point(640, 480));
		configurer.setShowCoolBar(false);
		configurer.setShowStatusLine(false);
		configurer.setShowMenuBar(true);
	}

	private void setFullScreenMode() {
		final IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
		configurer.setShowCoolBar(false);
		configurer.setShowStatusLine(false);
		configurer.setShowMenuBar(false);
	}

	public void postWindowCreate() {
		final Shell shell = getWindowConfigurer().getWindow().getShell();
		if (parameters.isSaverMode()) {
			shell.setMaximized(true);
			shell.setFullScreen(true);

			// black out all monitors but the primary monitor
			final Monitor[] monitors = getDisplay().getMonitors();
			final Monitor primaryMonitor = getDisplay().getPrimaryMonitor();
			for (int i = 0; i < monitors.length; i++) {
				if (monitors[i].equals(primaryMonitor)) {
					continue;
				}
				final Shell monitorShell = new Shell(shell, SWT.NO_TRIM
						| SWT.ON_TOP);
				monitorShell.setBounds(monitors[i].getBounds());
				monitorShell.setBackground(getDisplay().getSystemColor(
						SWT.COLOR_BLACK));
				addDisplayFilters(monitorShell);
				monitorShell.open();

			}
		}
		addDisplayFilters(shell);
	}

	private Display getDisplay() {
		return getWindowConfigurer().getWorkbenchConfigurer().getWorkbench()
				.getDisplay();
	}

	public void postWindowOpen() {
		if (parameters.isConfigurationMode()) {
			final IWorkbenchWindow window = getWindowConfigurer().getWindow();
			final UIJob job = new UIJob(window.getShell().getDisplay(),
					"showPreferences") {
				public IStatus runInUIThread(IProgressMonitor monitor) {
					ActionFactory.PREFERENCES.create(window).run();
					return Status.OK_STATUS;
				}
			};
			job.schedule();
		}
	}

	private void addDisplayFilters(final Shell shell) {
		if (EidlePreferences.isQuitOnMouseDownEnabled()
				&& parameters.isSaverMode()) {
			shell.getDisplay().addFilter(SWT.MouseMove, new Listener() {
				private int moveCount = 0;

				public void handleEvent(final Event event) {
					moveCount++;
					if (moveCount > 5) {
						PlatformUI.getWorkbench().close();
					}
				}
			});
		}
		if (parameters.isSaverMode()) {
			ScreenUtils.setCursorInvisible(shell);
			shell.getDisplay().addFilter(SWT.MouseDown, new Listener() {

				public void handleEvent(final Event event) {
					PlatformUI.getWorkbench().close();
				}
			});
		}
	}

	public void createWindowContents(final Shell shell) {
		if (parameters.isSaverMode()) {
			shell.setLayout(new FillLayout());
			getWindowConfigurer().createPageComposite(shell);
		} else {
			super.createWindowContents(shell);
		}
	}
}
